package JUC;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/*
*  4种拒绝策略
*   1 AbortPolicy：超过范围了就让调用者抛异常RejectedExecutionException【默认】；
    2 CallerRunsPolicy：让调用者运行任务（哪里来的回哪去，比如是在主线程调用的就让主线程自己执行任务）；
    3 DiscardPolicy：放弃本次任务(不抛异常，直接拒绝新任务然后结束程序)；
    4 DiscardOldestPolicy：放弃队列中最早的任务，新任务取代(不抛异常)；
*
*
* */
public class MyThreadPool {
    public static void main(String[] args) {
        // 自定义线程池 （7大参数）
        ThreadPoolExecutor myThreadPool = new ThreadPoolExecutor(
                2, // 核心线程数 ，就是正常情况下开放的线程数
                5, // 最大线程数，就是任务很多的情况下要用更多的资源去执行程序,线程数最大不超过这个值
                3, // 超时时间
                TimeUnit.SECONDS, // 超时时间单位
                new LinkedBlockingQueue<>(3), // 阻塞队列，相当于线程全部都在执行任务，但是又有新的任务进来了
                                                        // ，这时候可以在阻塞队列排队等待线程释放，最大排队数是自己传入的3
                Executors.defaultThreadFactory(),  // 线程工厂，直接默认的，没什么说法
                new ThreadPoolExecutor.AbortPolicy()); // 拒绝策略，当最大线程数和阻塞队列都满了，实在装不下了新任务了，
                                                                // 就要执行4种拒绝策略中的一种
        try{
            for (int i =0;i<20;i++){
                // execute()方法用来开启线程，传入Runnable对象，可以直接用lambda表达式重写run方法
                myThreadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName()+" 正在执行");
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 程序执行完成后要关闭线程
            myThreadPool.shutdown();
        }

        // 最大线程到底该如何设置（线程池调优的内容）？
        // 第一种 ；CPU密集型，看你的CPU的最大线程数是多少，然后设置成最大线程数(通过Runtime.getRuntime().availableProcessors()获取)
        // 第二种 ：IO密集型，看你的程序中的大型任务有几个（需自己判断），然后设置最大线程比大型任务的数量多就行了（最好是2倍）

    }
}
